﻿using System;
using System.IO;
using System.Net;

namespace GerbilLib
{
    public delegate void ResponseInfoDelegate(string statusDescription, long contentLength);
    public delegate void ProgressDelegate(int totalBytes, double percentComplete, double transferRate);
    public delegate void DoneDelegate();

    /// <summary>
    /// Base class for state object that gets passed around amongst async methods
    /// when doing async web request/response for data transfer. We store basic
    /// things that track current state of a download, including # bytes transfered,
    /// as well as some async callbacks that will get invoked at various points.
    /// </summary>
    abstract public class WebRequestState
    {
        /// <summary>
        /// Gets the default size of the buffer.
        /// </summary>
        /// <value>
        /// The default size of the buffer.
        /// </value>
        public static int DefaultBufferSize
        {
            get { return 1448; }
        }

        public int BytesRead { get; set; } // # bytes read during current transfer
        public long TotalBytes { get; set; } // Total bytes to read
        public double ProgressIncrement { get; set; } // delta % for each buffer read
        public Stream StreamResponse { get; set; } // Stream to read from
        public FileStream FileStream { get; set; } // Stream to write to
        public byte[] BufferRead { get; set; } // Buffer to read data into
        public DateTime TransferStart { get; set; } // Used for tracking xfr rate

        // Callbacks for response packet info & progress
        public ResponseInfoDelegate ResponseInfoCallback { get; set; }
        public ProgressDelegate ProgressCallback { get; set; }
        public DoneDelegate DoneCallback { get; set; }
        public virtual WebRequest Request { get; set; }
        public virtual WebResponse Response { get; set; }

        public WebRequestState(int bufferSize)
        {
            BytesRead = 0;
            BufferRead = new byte[bufferSize];
            StreamResponse = null;
            FileStream = null;
        }
    }

    /// <summary>
    /// State object for HTTP transfers
    /// </summary>
    public class HttpWebRequestState : WebRequestState
    {
        private HttpWebRequest _request;
        public override WebRequest Request
        {
            get { return _request; }
            set { _request = (HttpWebRequest)value; }
        }

        private HttpWebResponse _response;
        public override WebResponse Response
        {
            get { return _response; }
            set { _response = (HttpWebResponse)value; }
        }

        public HttpWebRequestState(int bufferSize) : base(bufferSize) { }
    }

    /// <summary>
    /// State object for FTP transfers
    /// </summary>
    public class FtpWebRequestState : WebRequestState
    {
        private FtpWebRequest _request;
        public override WebRequest Request
        {
            get { return _request; }
            set { _request = (FtpWebRequest)value; }
        }

        private FtpWebResponse _response;
        public override WebResponse Response
        {
            get { return _response; }
            set { _response = (FtpWebResponse)value; }
        }

        public FtpWebRequestState(int bufferSize) : base(bufferSize) { }
    }
}
